package com.wang.pojo;

import com.wang.util.ModBusUtil;
import lombok.Data;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

@Data
public class SendDemoTest {

    //地址位
    private String addressCode;
    //功能码
    private String funCode;

    private String startHexStr;

    //数据块
    private String dataCode;
    //crc校验
    private String crcCode;



/*    public static void main(String[] args) {

        SendDemoTest sendDemoTest = new SendDemoTest();
        sendDemoTest.setAddressCode("03");
        sendDemoTest.setFunCode("03");



        List<SendDemo> sendDemoList = new ArrayList<>();

        SendDemo sendDemo1 = new SendDemo();
        sendDemo1.setName("电导率");
        sendDemo1.setDataType("FLOAT");
        sendDemo1.setStartHexStr("0600");
        sendDemo1.setNumMade(0);
        sendDemo1.setReserveNum(2);



        SendDemo sendDemo2 = new SendDemo();
        sendDemo2.setName("电阻率");
        sendDemo2.setDataType("FLOAT");
        sendDemo2.setStartHexStr("0602");
        sendDemo2.setNumMade(0);
        sendDemo2.setReserveNum(2);

        SendDemo sendDemo3 = new SendDemo();
        sendDemo3.setName("TDS");
        sendDemo3.setDataType("FLOAT");
        sendDemo3.setStartHexStr("0604");
        sendDemo3.setNumMade(0);
        sendDemo3.setReserveNum(2);


        SendDemo sendDemo4 = new SendDemo();
        sendDemo4.setName("温度");
        sendDemo4.setDataType("INT");
        sendDemo4.setStartHexStr("0606");
        sendDemo4.setNumMade(10);
        sendDemo4.setReserveNum(2);

        SendDemo sendDemo5 = new SendDemo();
        sendDemo5.setName("电极常数");
        sendDemo5.setDataType("INT");
        sendDemo5.setStartHexStr("0607");
        sendDemo5.setNumMade(1000);
        sendDemo5.setReserveNum(3);

        sendDemoList.add(sendDemo1);
        sendDemoList.add(sendDemo2);
        sendDemoList.add(sendDemo3);
        sendDemoList.add(sendDemo4);
        sendDemoList.add(sendDemo5);





        makeUpCommand(sendDemoTest ,sendDemoList);


        byte[] bytes = {0x03, 0x03, 0x10, 0x42, (byte) 0xf6, (byte) 0xbe, 0x12,0x41,0x01,
                (byte) 0xb0, (byte) 0x9c,0x42,0x78, (byte) 0xbe,0x12,0x00, (byte) 0xef,0x00,0x49, (byte) 0xf4, (byte) 0xbb};

        readData(sendDemoTest ,sendDemoList,bytes);


    }*/


   /* public static void main(String[] args) {

        SendDemoTest sendDemoTest = new SendDemoTest();
        sendDemoTest.setAddressCode("03");
        sendDemoTest.setFunCode("03");



        List<SendDemo> sendDemoList = new ArrayList<>();

        SendDemo sendDemo0 = new SendDemo();
        sendDemo0.setName("溶解氧1");
        sendDemo0.setDataType("INT");
        sendDemo0.setStartHexStr("0400");
        sendDemo0.setNumMade(10);
        sendDemo0.setReserveNum(0);


        SendDemo sendDemo1 = new SendDemo();
        sendDemo1.setName("溶解氧");
        sendDemo1.setDataType("INT");
        sendDemo1.setStartHexStr("0401");
        sendDemo1.setNumMade(100);
        sendDemo1.setReserveNum(0);



        SendDemo sendDemo2 = new SendDemo();
        sendDemo2.setName("温度");
        sendDemo2.setDataType("INT");
        sendDemo2.setStartHexStr("0402");
        sendDemo2.setNumMade(10);
        sendDemo2.setReserveNum(0);

        SendDemo sendDemo3 = new SendDemo();
        sendDemo3.setName("电流值");
        sendDemo3.setDataType("INT");
        sendDemo3.setStartHexStr("0403");
        sendDemo3.setNumMade(0);
        sendDemo3.setReserveNum(0);




        sendDemoList.add(sendDemo0);
        sendDemoList.add(sendDemo1);
        sendDemoList.add(sendDemo2);
        sendDemoList.add(sendDemo3);






        makeUpCommand(sendDemoTest ,sendDemoList);


        byte[] bytes = {0x01, 0x03,0x08, 0x1D, 0x2A, (byte) 0xC5, 0x45, (byte) 0xFE, 0x56, 0x1C, (byte) 0xA6, 0x5B, 0x58};

        readData(sendDemoTest ,sendDemoList,bytes);

    }*/

    public static void main(String[] args) {

        SendDemoTest sendDemoTest = new SendDemoTest();
        sendDemoTest.setAddressCode("01");
        sendDemoTest.setFunCode("03");


        List<SendDemo> sendDemoList = new ArrayList<>();

        SendDemo sendDemo0 = new SendDemo();
        sendDemo0.setName("余氯");
        sendDemo0.setDataType("FLOAT");
        sendDemo0.setStartHexStr("1000");
        sendDemo0.setNumMade(0);
        sendDemo0.setReserveNum(1);
        sendDemo0.setByteType("BL");

        SendDemo sendDemo1 = new SendDemo();
        sendDemo1.setName("余氯电流");
        sendDemo1.setDataType("FLOAT");
        sendDemo1.setStartHexStr("1002");
        sendDemo1.setNumMade(0);
        sendDemo1.setReserveNum(2);
        sendDemo1.setByteType("BL");

        SendDemo sendDemo3 = new SendDemo();
        sendDemo3.setName("pH");
        sendDemo3.setDataType("FLOAT");
        sendDemo3.setStartHexStr("1004");
        sendDemo3.setNumMade(0);
        sendDemo3.setReserveNum(1);
        sendDemo3.setByteType("BL");

        SendDemo sendDemo4 = new SendDemo();
        sendDemo4.setName("余氯温度");
        sendDemo4.setDataType("FLOAT");
        sendDemo4.setStartHexStr("1006");
        sendDemo4.setNumMade(0);
        sendDemo4.setReserveNum(1);
        sendDemo4.setByteType("BL");


        sendDemoList.add(sendDemo0);
        sendDemoList.add(sendDemo1);
        sendDemoList.add(sendDemo3);
        sendDemoList.add(sendDemo4);


        makeUpCommand(sendDemoTest, sendDemoList);


        byte[] bytes = {0x01, 0x03, 0x10, (byte) 0xCC, (byte) 0xCD, 0x3D, (byte) 0xCC, (byte) 0x99, (byte) 0x9A, 0x3E,
                0x19, 0x00, 0x00, 0x40, (byte) 0xF0, 0x00, 0x00, 0x41, (byte) 0xCC, 0x2b, 0x64};

        readData(sendDemoTest, sendDemoList, bytes);

    }


    //生成命令
    public static void makeUpCommand(SendDemoTest sendDemoTest, List<SendDemo> sendDemoList) {

        //重新排序  按照开始字节大小排序
        List<SendDemo> newSendDemoList = search(sendDemoList);

        //设置开始位置
        sendDemoTest.setStartHexStr(newSendDemoList.get(0).getStartHexStr());

        //设置命令  发送寄存器数目
        //拿到第一个 和最后一个
        SendDemo firstSendDemo = newSendDemoList.get(0);
        SendDemo lastSendDemo = newSendDemoList.get(newSendDemoList.size() - 1);
        //计算发送命令的长度
        Integer firstnum = ModBusUtil.hex2decimal(firstSendDemo.getStartHexStr());
        Integer lastnum = ModBusUtil.hex2decimal(lastSendDemo.getStartHexStr());
        Integer count = lastnum - firstnum + 2;


        //组合命令
        String command = sendDemoTest.getAddressCode();
        command += sendDemoTest.getFunCode();
        command += sendDemoTest.getStartHexStr();
        //添加长度
        String lenstr = ModBusUtil.decToHex16(count);
        command += lenstr;


        byte[] bytes = ModBusUtil.HexString2Bytes(command);

        String crc1 = ModBusUtil.getCRC3(bytes);
        command += crc1;
        //最终要发送的字符数组
        byte[] aa = ModBusUtil.HexString2Bytes(command);


        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < command.length(); i++) {
            sb.append(command.substring(i, i + 1));

            if (i > 0 && i < command.length() && ((i + 1) % 2) == 0) {
                sb.append(" ");
            }
        }


        System.out.println("生成的命令：" + sb.toString());

    }


    //解析命令数据
    public static void readData(SendDemoTest sendDemoTest, List<SendDemo> sendDemoList, byte[] bytes) {
        //重新排序  按照开始字节大小排序
        List<SendDemo> newSendDemoList = search(sendDemoList);

        //设置开始位置
        sendDemoTest.setStartHexStr(newSendDemoList.get(0).getStartHexStr());

        //赋予开始地址 结束地址
        for (SendDemo sendDemo : newSendDemoList) {
            Integer start = (ModBusUtil.hex2decimal(sendDemo.getStartHexStr()) - ModBusUtil.hex2decimal(sendDemoTest.getStartHexStr())) * 2;

            if (sendDemo.getDataType().equals("FLOAT") || sendDemo.getDataType().equals("LONG")) {
                //float 占4个字节
                sendDemo.setStartSite(start);
                sendDemo.setEndSite(start + 3);
            } else if (sendDemo.getDataType().equals("INT")) {
                sendDemo.setStartSite(start);
                sendDemo.setEndSite(start + 1);
            }
        }


        //开始解析
        //先将bytes 转换成16进制字符串
        String baseData = ModBusUtil.bytes2HexString(bytes);

        String baseDataStr = baseData.replaceAll(" ", "");

        //转换成数组
        String[] baseDatas = baseData.split(" ");

        //要校验的数据
        String[] checkDatas = Arrays.copyOfRange(baseDatas, 0, baseDatas.length - 2);
        StringBuffer sb1 = new StringBuffer();
        for (String s : checkDatas) {
            sb1.append(s);
        }

        byte[] checkBytes = ModBusUtil.HexString2Bytes(sb1.toString());


        //计算crc值
        String checkCrc2 = ModBusUtil.getCRC3(checkBytes);
        //截取原有crc值
        String checkCrc1 = baseDataStr.substring(baseDataStr.length() - 4);

        if (checkCrc1.equals(checkCrc2)) {
            System.out.println("校验通过");

            for (SendDemo sendDemo : sendDemoList) {


                String[] dataStr2 = Arrays.copyOfRange(baseDatas, sendDemo.getStartSite() + 3, sendDemo.getEndSite() + 4);

                //重新排序
                String[] lastDatas = ModBusUtil.convertBBLL(sendDemo.getByteType(), dataStr2);

                StringBuffer data1 = new StringBuffer();
                for (String ss : lastDatas) {
                    data1.append(ss);
                }
                //开始解析数据
                if (sendDemo.getDataType().equals("FLOAT") || sendDemo.getDataType().equals("LONG")) {

                    float floatData = ModBusUtil.hex2decimalFloat(data1.toString());

                    //规则
                    if (sendDemo.getReserveNum() != 0) {
                        String pattern = "0.";
                        for (int i = 0; i < sendDemo.getReserveNum(); i++) {
                            pattern += 0;
                        }
                        DecimalFormat df = new DecimalFormat(pattern);
                        String str = df.format(floatData);
                        System.out.println("参数：" + sendDemo.getName() + " :" + str);
                    } else {
                        int hh = (int) floatData;

                        System.out.println("参数：" + sendDemo.getName() + " :" + hh);
                    }

                } else if (sendDemo.getDataType().equals("INT")) {
                    Integer dd = ModBusUtil.hex2decimal(data1.toString());

                    double doubleData = Double.valueOf(dd);

                    if (sendDemo.getNumMade() != 0) {
                        doubleData = doubleData / sendDemo.getNumMade();
                    }

                    //规则
                    if (sendDemo.getReserveNum() != 0) {
                        String pattern = "0.";
                        for (int i = 0; i < sendDemo.getReserveNum(); i++) {
                            pattern += 0;
                        }
                        DecimalFormat df = new DecimalFormat(pattern);
                        String str = df.format(doubleData);

                        System.out.println("参数：" + sendDemo.getName() + " :" + str);
                    } else {
                        int hh = (int) doubleData;

                        System.out.println("参数：" + sendDemo.getName() + " :" + hh);
                    }

                }

            }

        } else {
            System.out.println("校验不通过");

        }

    }


    // 方式4: 升序排列
    public static List<SendDemo> search(List<SendDemo> sendDemoList) {
        Collections.sort(sendDemoList, new Comparator<SendDemo>() {
            @Override
            public int compare(SendDemo o1, SendDemo o2) {
                return o1.getStartHexStr().compareTo(o2.getStartHexStr());
            }
        });
        return sendDemoList;
    }


}
